/**
    MVP Tree data structure using graph database for I/O storage
    Copyright (C) 2014  David G. Starkweather

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.

    David Starkweather starkd88@gmail.com
**/

package org.phash.mvptree;

import java.lang.StrictMath;
import org.neo4j.graphdb.Node;
import org.neo4j.graphdb.Transaction;

/** 
 * Datapoint class for representing units of
 * data as byte[].
 **/
public class ByteDatapoint extends Datapoint {

    public ByteDatapoint(Node node){
	super(node);
    }

    public ByteDatapoint(Node node, byte[] data){

	super(node);
	setData(data);

    }

    ByteDatapoint(Datapoint point){
	super(point);
    }


    public void setData(byte[] data) {
	Node node = getNode();
	Transaction tx = node.getGraphDatabase().beginTx();
	try {
	    node.setProperty(DATA, data);
	    tx.success();
	}finally {
	    tx.finish();
	}
    }

    public byte[] getData() {
	Node node = getNode();
	Transaction tx = node.getGraphDatabase().beginTx();
	byte[] data = null;
	try {
	    data = (byte[])node.getProperty(DATA);
	    tx.success();
	} finally {
	    tx.finish();
	}
	return data;
    }

    /**
     * compute L1 distance betweeen two points 
     *
     * @param point other Datapoint with which to compare
     * @return float val for distance between two points 
     *
     **/
    public float distance(Datapoint point){
	Datapoint.incrementNumOps();

	if (point == null)
	    throw new BadDistanceValueException("null");

	ByteDatapoint otherPoint = (ByteDatapoint)point;
	byte[] dataA = getData();
	byte[] dataB = otherPoint.getData();

	if (dataA == null || dataB == null || dataA.length != dataB.length) 
	    throw new BadDistanceValueException();

	int sum = 0;
	for (int i=0;i<dataA.length;i++){
	    sum += Math.abs((int)dataA[i] - (int)dataB[i]);
	}
	
	return (float)sum/(float)dataA.length;

    }

}
